package com.dzsw.javabase.file;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;

public class CopyDirectorySample {

    public static void main(String[] args) throws Exception {
//        String original = "D:/mybatis3Gen";
//        String target = "D:/works/temp/mybatis3Gen";
//        String p = "D:\\mybatis3Gen\\src\\main\\java\\jp\\co\\binal\\toss\\domain\\controller\\AttentionController.java";
//        copyDirectory(original, target).stream().forEach(System.out::println);
//        System.out.println("copy done.");

        String op = "\\\\192.168.1.31\\Users\\Sun_Zhe\\YRQtest";
        String tp = "D:/works/temp/";
        copyDirectory(op, tp).stream().forEach(System.out::println);

//        System.out.println(CopyDirectorySample.getDirectoryFileNumber(original));
//        System.out.println(CopyDirectorySample.getDirectoryFileNumber(p));
    }


    public static void copyDirectoryFast(String original, String target) throws Exception {
        Path sourceDirectory = Path.of(original);
        Path targetDirectory = Path.of(target);
        System.out.println(Files.isRegularFile(targetDirectory));
        try {
            // 复制目录及其子目录中的所有文件
            Files.walk(sourceDirectory).filter(Files::isRegularFile) // 过滤路径
                    .forEach(sourceFile -> {
                        try {
                            Path targetFile = targetDirectory.resolve(sourceDirectory.relativize(sourceFile));
                            Files.createDirectories(targetFile.getParent());
                            Files.copy(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 首先定义源目录和目标目录的 Path 对象。然后使用 Files.walk 方法遍历源目录及其子目录中的所有文件。通过过滤器判断当前遍历到的文件是否为普通文件，然后使用 forEach 方法对每个文件进行复制操作。
     * <p>
     * 在复制过程中，首先根据源目录和当前文件的相对路径，计算出目标目录中对应的路径。然后使用 Files.createDirectories 方法创建目标文件所在的父目录（如果不存在的话）。最后使用Files.copy
     * 方法将源文件复制到目标文件，并指定 StandardCopyOption.REPLACE_EXISTING 选项来替换已存在的目标文件。
     * <p>
     * 需要注意的是，上述代码中的源目录和目标目录都是相对路径，可以根据实际情况进行修改。另外，如果目标目录已存在同名文件，使用 StandardCopyOption.REPLACE_EXISTING 选项可以替换已存在的文件。
     *
     * @param original 源路径
     * @param target   目标路径
     * @return 所有文件及文件夹列表
     * @throws Exception IOException
     */
    public static List<FileItem> copyDirectory(String original, String target) throws Exception {
        List<FileItem> list = new ArrayList<>();

        Path sourceDirectory = Path.of(original);
        Path targetDirectory = Path.of(target);
        /** jdk 1.8 使用以下两条语句创建 Path 对象。 */
//        Path sourceDirectory = FileSystems.getDefault().getPath(original);
//        Path targetDirectory = FileSystems.getDefault().getPath(target);

        Files.walk(sourceDirectory).forEach(sourceFile -> {
            try {
                // 获取目标路径
                Path targetFile = targetDirectory.resolve(sourceDirectory.relativize(sourceFile));
                if (Files.isDirectory(sourceFile)) {
                    list.add(FileItem.builder()
                            .path(sourceFile.toString())
                            .name(sourceFile.getFileName().toString())
                            .parent(sourceFile.getParent().toString())
                            .isDirectory(true)
                            .build());
                    Files.createDirectories(targetFile);
                } else {
                    list.add(FileItem.builder()
                            .path(sourceFile.toString())
                            .name(sourceFile.getFileName().toString())
                            .parent(sourceFile.getParent().toString())
                            .isDirectory(false)
                            .build());
                    Files.copy(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
        return list;
    }

    public static long getDirectoryFileNumber(String path) throws IOException {
        long number = 0;
        Path p = Path.of(path);
        if (Files.isDirectory(p)) {
            number = Files.list(p).count();
        }
        return number;
    }
}
